package com.thinkTank.oa.lucene;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/***
 * solr检索工具类
 * @date 2018-09-12
 * @author dq
 *
 */
public class SolrUtils {
	private final static Logger logger = LoggerFactory.getLogger(SolrUtils.class);

	private static final String baseURL = "http://localhost:88/solr/"; 
	private static SolrServer projectServer = new HttpSolrServer(baseURL + "project");
	private static SolrServer demanServer = new HttpSolrServer(baseURL + "demand");
	private static SolrServer personServer = new HttpSolrServer(baseURL + "person");
	private static SolrServer confServer = new HttpSolrServer(baseURL + "conf");
	private static SolrServer costomServer = new HttpSolrServer(baseURL + "customer");
	
	public static Pagination search(String target, String keywords,List<String> fields, int pageNo, int pageSize)  {
		try {
			SolrQuery query = new SolrQuery();
			query.set("start", (pageNo-1)*pageSize);
			query.set("rows", pageSize);
			query.setQuery(keywords);
			query.setHighlightFragsize(1000);
			query.setHighlight(true); // 开启高亮组件或用query.setParam("hl", "true");  
			if(null!=fields){
				for (String	field : fields) {
//					query.setQuery(field+":"+keywords);
					query.addHighlightField(field);
				}
			}
			query.add("hl.preserveMulti","true");
	        query.setHighlightSimplePre("<font color='red'>");//标记，高亮关键字前缀  
	        query.setHighlightSimplePost("</font>");//后缀  
			if (target.equals("project")) {
				QueryResponse rsp = projectServer.query(query);
				SolrDocumentList list = rsp.getResults();
				int totalCount = Integer.parseInt(list.getNumFound() + "");
				Pagination p = new Pagination(pageNo, pageSize, totalCount);
				if (totalCount < 1) {
					p.setList(new ArrayList());
					return p;
				}
				p.setList(queryHighter(list,rsp.getHighlighting(),fields,LuceneProject.class,"projectId"));
				return p;
			} 	if (target.equals("demand")) {
				QueryResponse rsp = demanServer.query(query);
				SolrDocumentList list = rsp.getResults();
				int totalCount = Integer.parseInt(list.getNumFound() + "");
				Pagination p = new Pagination(pageNo, pageSize, totalCount);
				if (totalCount < 1) {
					p.setList(new ArrayList());
					return p;
				}
				p.setList(queryHighter(list,rsp.getHighlighting(),fields,LuceneDemand.class,"demandId"));
				return p;
			}		
			if (target.equals("person")) {
				QueryResponse rsp = personServer.query(query);
				SolrDocumentList list = rsp.getResults();
				int totalCount = Integer.parseInt(list.getNumFound() + "");
				Pagination p = new Pagination(pageNo, pageSize, totalCount);
				if (totalCount < 1) {
					p.setList(new ArrayList());
					return p;
				}
				p.setList(queryHighter(list,rsp.getHighlighting(),fields,LucenePerson.class,"expertId"));
				return p;
			}
			if (target.equals("customer")) {
				QueryResponse rsp = costomServer.query(query);
				SolrDocumentList list = rsp.getResults();
				int totalCount = Integer.parseInt(list.getNumFound() + "");
				Pagination p = new Pagination(pageNo, pageSize, totalCount);
				if (totalCount < 1) {
					p.setList(new ArrayList());
					return p;
				}
				p.setList(queryHighter(list,rsp.getHighlighting(),fields,LuceneCustomer.class,"customerId"));
				return p;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	public static Pagination relate(String target, String keywords,List<String> fields, int pageNo, int pageSize)  {
		try {
			SolrQuery query = new SolrQuery();
			query.set("start", (pageNo-1)*pageSize);
			query.set("rows", pageSize);
			query.setQuery(keywords);
			query.addField("paperId");
			query.addField("title");
			query.setHighlight(true); // 开启高亮组件或用query.setParam("hl", "true");  
			query .setParam("mlt", "true")  
	            .setParam("mlt.fl", "title")  
	            .setParam("mlt.mindf", "1")  
	            .setParam("mlt.mintf", "1")  
	            .setParam("mlt.count", String.valueOf(pageSize)); 
		if (target.equals("project")) {
				QueryResponse rsp = projectServer.query(query);
				SimpleOrderedMap<SolrDocumentList> mltResults = (SimpleOrderedMap<SolrDocumentList>) rsp.getResponse().get("moreLikeThis");

				SolrDocumentList  list=mltResults.getVal(0);
				int totalCount = Integer.parseInt(list.getNumFound() + "");
				Pagination p = new Pagination(pageNo, pageSize, totalCount);
				if (totalCount < 1) {
					p.setList(new ArrayList());
					return p;
				}
				p.setList(queryHighter(list, null, null, LuceneProject.class, "projectId"));
				return p;
			}
		if (target.equals("demand")) {
			QueryResponse rsp = demanServer.query(query);
			SimpleOrderedMap<SolrDocumentList> mltResults = (SimpleOrderedMap<SolrDocumentList>) rsp.getResponse().get("moreLikeThis");

			SolrDocumentList  list=mltResults.getVal(0);
			int totalCount = Integer.parseInt(list.getNumFound() + "");
			Pagination p = new Pagination(pageNo, pageSize, totalCount);
			if (totalCount < 1) {
				p.setList(new ArrayList());
				return p;
			}
			p.setList(queryHighter(list, null, null, LuceneDemand.class, "demandId"));
			return p;
		}		
		if (target.equals("person")) {
			QueryResponse rsp = personServer.query(query);
			SimpleOrderedMap<SolrDocumentList> mltResults = (SimpleOrderedMap<SolrDocumentList>) rsp.getResponse().get("moreLikeThis");

			SolrDocumentList  list=mltResults.getVal(0);
			int totalCount = Integer.parseInt(list.getNumFound() + "");
			Pagination p = new Pagination(pageNo, pageSize, totalCount);
			if (totalCount < 1) {
				p.setList(new ArrayList());
				return p;
			}
			p.setList(queryHighter(list, null, null, LucenePerson.class, "expertId"));
			return p;
		}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}
	/**
     * 根据关键字查询 [测试通过 - 使用 solr内部转换机制]
	 * @param <T>
     * @param <T>
     * @param server    solr客户端
     * @param keyword    搜索关键字
     * @param pageNum    当前页码
     * @param pageSize    每页显示的大小
     * @param clzz        对象类型
     * @return
     */
    public static <T> List<T> queryHighter(SolrDocumentList solrDocuments,Map<String,Map<String,List<String>>> highlightMap,List<String> hlField,Class<T> clzz,String idName){
        //查询结果集
        List<T> items = new ArrayList<T>();
        try {
            Object obj = null;
            Method m = null;
            Class<?> fieldType = null;
            for(SolrDocument solrDocument : solrDocuments) {
                    obj = clzz.newInstance();
                    Collection<String> fieldNames = solrDocument.getFieldNames();            //得到所有的属性名
                    for (String fieldName : fieldNames) {
                        //需要说明的是返回的结果集中的FieldNames()比类属性多
                        Field[] filedArrays = clzz.getDeclaredFields();                     //获取类中所有属性
                        
                        for (Field f : filedArrays) {    
                            //如果实体属性名和查询返回集中的字段名一致,填充对应的set方法
                            if(f.getName().equals(fieldName)){
                                
                                //获取到的属性名
                                //private java.lang.String com.test.model.Article.id
                                f = clzz.getDeclaredField(fieldName);    
//                                clzz.getDeclaredField(fieldName).getType()
                                //属性类型
                                //private java.lang.String com.test.model.Article.id
                                fieldType = f.getType();    
                                
                                //构造set方法名  setId
                                String dynamicSetMethod = dynamicMethodName(f.getName(), "set");
                                
                                //获取方法
                                //public void com.test.model.Article.setId(java.lang.String)
                                m = clzz.getMethod(dynamicSetMethod, fieldType);
                                
                                //获取到的值
                                logger.info(f.getName() + "-->" + dynamicSetMethod+ "=" + solrDocument.getFieldValue(fieldName));
                                
                                //获取fieldType类型
                                fieldType = getFileType(fieldType);
                                
                                //获取到的属性
                                m.invoke(obj, solrDocument.getFieldValue(fieldName));
                                if(hlField!=null){
                                for(String hl : hlField){
                                    if(hl.equals(fieldName)){
                                        String idv = solrDocument.getFieldValue(idName).toString();
                                        List<String> hlfList=highlightMap.get(idv).get(fieldName);
                                        if(null!=hlfList && hlfList.size()>0){
                                            //高亮添加
                                        	if(fieldType.getName().equals(ArrayList.class.getName())){
                                        		m.invoke(obj, fieldType.cast(hlfList));
                                        	}else{
                                        		m.invoke(obj, fieldType.cast(hlfList.get(0)));
                                        	}
                                            
                                        }else{
                                            //正常添加
                                            m.invoke(obj, solrDocument.getFieldValue(fieldName));
                                        }
                                    }
                                }
                                }
                                
                            }
                        }
                    }
                    items.add(clzz.cast(obj));
            }
            
        } catch (Exception e) {
        	logger.error("highlighter query error." + e.getMessage(), e);
            e.printStackTrace();
        }

        //填充page对象
        return items;
    }
    private static String dynamicMethodName(String fieldName,String methodType){
    	fieldName=fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
    	return methodType+fieldName;
    }
    public static Class<?> getFileType(Class<?> fieldType){
        if (fieldType.getName().equals(Integer.class.getName())) {
            return Integer.class;
        } else if (fieldType.getName().equals(Float.class.getName())) {
            return Float.class;
        } else if (fieldType.getName().equals(Double.class.getName())) {
            return  Double.class;
        } else if (fieldType.getName().equals(Boolean.class.getName())) {
            return  Boolean.class;
        } else if (fieldType.getName().equals(Short.class.getName())) {
            return  Short.class;
        } else if (fieldType.getName().equals(Long.class.getName())) {
            return  Long.class;
        } else if(fieldType.getName().equals(String.class.getName())){
            return  String.class;
        }else if(fieldType.getName().equals(Collection.class.getName())){
            return  Collection.class;
        }else if(fieldType.getName().equals(String[].class.getName())){
        	return String[].class;
        }else if(fieldType.getName().equals(ArrayList.class.getName())){
        	return ArrayList.class;
        }else if(fieldType.getName().equals(List.class.getName())){
        	return ArrayList.class;
        }
        return null;
    }
	
	
	/**
	 * 添加索引
	 * @date  2018-09-13
	 * @author dq
	 * @param target  添加索引的目标对象
	 * @param beans 需要添加的索引
	 * @return
	 */
	public static boolean add(String target, List beans) {
		try {
			if (target.equals("project")) {
				projectServer.addBeans(beans);
				projectServer.commit();
			} else if (target.equals("demand")) {
				demanServer.addBeans(beans);
				demanServer.commit();
			}else if (target.equals("person")) {
				personServer.addBeans(beans);
				personServer.commit();
			}else if (target.equals("conf")) {
				confServer.addBeans(beans);
				confServer.commit();
			}else if (target.equals("customer")) {
				costomServer.addBeans(beans);
				costomServer.commit();
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage());
			return false;
		}
	}
	
	/***
	 * 删除索引
	 * @date 2018-09-13
	 * @author dq
	 * @param target
	 * @param ids
	 * @return
	 */
	public static boolean delete(String target, List ids) {
		try {
			
			if (target.equals("project")) {
				projectServer.deleteById(ids);
				projectServer.commit();
			} else if (target.equals("demand")) {
				demanServer.deleteById(ids);
				demanServer.commit();
			}else if (target.equals("person")) {
				personServer.deleteById(ids);
				personServer.commit();
			}else if (target.equals("conf")) {
				confServer.deleteById(ids);
				confServer.commit();
			}else if (target.equals("customer")) {
				costomServer.deleteById(ids);
				costomServer.commit();
			}
			return true;
		} catch (Exception e) {
			logger.error(e.getMessage());
			return false;
		}

	}
	/***
	 * 更新索引
	 * @author dq
	 * @date 2018-09-13
	 * @param target
	 * @param beans
	 * @return
	 */
	public static boolean update(String target, List beans) {
		try {
			
			if (target.equals("project")) {
				projectServer.addBeans(beans);
				projectServer.commit();
			} else if (target.equals("demand")) {
				demanServer.addBeans(beans);
				demanServer.commit();
			}else if (target.equals("person")) {
				personServer.addBeans(beans);
				personServer.commit();
			}else if (target.equals("conf")) {
				confServer.addBeans(beans);
				confServer.commit();
			}else if (target.equals("customer")) {
				costomServer.addBeans(beans);
				costomServer.commit();
			}
		
			return true;
		} catch (Exception e) {
			logger.error(e.getMessage());
			return false;
		}
	}
	
	/***
	 * 删除目标对象的 的所有索引
	 * @date 2018-09-13
	 * @author dq
	 * @param target
	 * @return
	 */
	public static boolean deleteAll(String target) {
		try {
			
			if (target.equals("project")) {
				projectServer.deleteByQuery("*:*");
				projectServer.commit();
			} else if (target.equals("demand")) {
				demanServer.deleteByQuery("*:*");
				demanServer.commit();
			}else if (target.equals("person")) {
				personServer.deleteByQuery("*:*");
				personServer.commit();
			}else if (target.equals("conf")) {
				confServer.deleteByQuery("*:*");
				confServer.commit();
			}else if (target.equals("customer")) {
				costomServer.deleteByQuery("*:*");
				costomServer.commit();
			}
			return true;
		} catch (Exception e) {
			logger.error(e.getMessage());
			return false;
		}

	}
	
	public static void main(String[] args) {
//		LuceneProject lp = new LuceneProject();
//		lp.setProjectId("1232131231231232");
//		lp.setProjectName("湖州赛尔迪生物医药科技有限公司");
//		List<LuceneProject>  pp = new ArrayList<LuceneProject>();
//		pp.add(lp);
//		boolean flag = SolrUtils.add("project", pp);
//		System.out.println(flag);
		Pagination p =SolrUtils.search("project", "projectName:湖州", null, 1, 10);
		for(int i=0;i<p.getList().size();i++){
			LuceneProject lup = (LuceneProject)p.getList().get(i);
			System.out.println(lup.getProjectName());
		}
		
	}
}
